#include "PluginManager.h"
#include "Depends/RapidXML/rapidxml.hpp"
#include "Depends/RapidXML/rapidxml_iterators.hpp"
#include "Depends/RapidXML/rapidxml_print.hpp"
#include "Depends/RapidXML/rapidxml_utils.hpp"
#include "PluginModule/IPlugin.h"
#include "PluginModule/Platform.h"

#if FG_PLATFORM == FG_PLATFORM_WIN
#pragma warning(disable:4996)
#pragma comment( lib, "ws2_32.lib" )
#endif

#ifdef FG_DEBUG_MODE

#if FG_PLATFORM == FG_PLATFORM_WIN

#elif FG_PLATFORM == FG_PLATFORM_LINUX || FG_PLATFORM == FG_PLATFORM_ANDROID
#elif FG_PLATFORM == FG_PLATFORM_APPLE || FG_PLATFORM == FG_PLATFORM_APPLE_IOS
#endif

#else

#if FG_PLATFORM == FG_PLATFORM_WIN

#elif FG_PLATFORM == FG_PLATFORM_LINUX || FG_PLATFORM == FG_PLATFORM_ANDROID
#elif FG_PLATFORM == FG_PLATFORM_APPLE || FG_PLATFORM == FG_PLATFORM_APPLE_IOS
#endif

#endif


#ifndef FG_DYNAMIC_PLUGIN
//for nf-sdk plugins
//#include "NFComm/NFActorPlugin/NFActorPlugin.h"
//#include "NFComm/NFConfigPlugin/NFConfigPlugin.h"
//#include "NFComm/NFKernelPlugin/NFKernelPlugin.h"
#include "LogPlugin/LogPlugin.h"
#include "ConfigPlugin/ConfigPlugin.h"
#include "SecurityPlugin/SecurityPlugin.h"
//#include "NFComm/NFLuaScriptPlugin/NFLuaScriptPlugin.h"
//#include "NFComm/NFNavigationPlugin/NFNavigationPlugin.h"
#include "NetPlugin/NetPlugin.h"
//#include "NFComm/NFNoSqlPlugin/NFNoSqlPlugin.h"
//#include "NFComm/NFScalePlugin/NFScalePlugin.h"
//#include "SecurityPlugin/SecurityPlugin.h"
//#include "NFComm/NFTestPlugin/NFTestPlugin.h"
////DB
//#include "NFServer/NFDBLogicPlugin/NFDBLogicPlugin.h"
//#include "NFServer/NFDBNet_ClientPlugin/NFDBNet_ClientPlugin.h"
//#include "NFServer/NFDBNet_ServerPlugin/NFDBNet_ServerPlugin.h"
////GAME
//#include "NFServer/NFGameLogicPlugin/NFGameLogicPlugin.h"
//#include "NFServer/NFGameServerNet_ClientPlugin/NFGameServerNet_ClientPlugin.h"
//#include "NFServer/NFGameServerNet_ServerPlugin/NFGameServerNet_ServerPlugin.h"
//#include "NFServer/NFGameServerPlugin/NFGameServerPlugin.h"
////LOGIN
//#include "NFServer/NFLoginLogicPlugin/NFLoginLogicPlugin.h"
//#include "NFServer/NFLoginNet_ClientPlugin/NFLoginNet_ClientPlugin.h"
//#include "NFServer/NFLoginNet_ServerPlugin/NFLoginNet_ServerPlugin.h"
//#include "NFServer/NFLoginNet_HttpServerPlugin/NFLoginNet_HttpServerPlugin.h"
//MASTER
//#include "NFServer/NFMasterNet_HttpServerPlugin/NFMasterNet_HttpServerPlugin.h"
#include "Server/MasterNetServer/MasterNetServerPlugin.h"
//PROXY
#include "Server/ProxyLogicPlugin/ProxyLogicPlugin.h"
#include "Server/ProxyNetClient/ProxyServerNetClientPlugin.h"
#include "Server/ProxyNetServer/ProxyServerNetServerPlugin.h"
////WORLD
//#include "NFServer/NFWorldLogicPlugin/NFWorldLogicPlugin.h"
#include "Server/WorldNetClient/WorldNetClientPlugin.h"
#include "Server/WorldNetServer/WorldNetServerPlugin.h"
#endif

using namespace FragrantGrass;

void FragrantGrass::CoroutineExecute(void* arg)
{
	PluginManager::Instance()->Execute();
}

FragrantGrass::PluginManager::PluginManager() : IPluginManager()
{
	mnAppID = 0;
    mbIsDocker = false;

	mCurrentPlugin = nullptr;
	mCurrenModule = nullptr;

#ifdef FG_DYNAMIC_PLUGIN
	mbStaticPlugin = false;
#else
	mbStaticPlugin = true;
#endif

	mnInitTime = time(NULL);
	mnNowTime = mnInitTime;

	mGetFileContentFunctor = nullptr;

	mstrConfigPath = "./";

#ifdef FG_DEBUG_MODE
   mstrConfigName = "DataCfg/Debug/Plugin.xml";
#else
   mstrConfigName = "DataCfg/Release/Plugin.xml";
#endif
}

FragrantGrass::PluginManager::~PluginManager()
{

}

bool FragrantGrass::PluginManager::LoadPlugin()
{
	std::cout << "----LoadPlugin----" << std::endl;

	LoadPluginConfig();

#ifndef FG_DYNAMIC_PLUGIN
	LoadStaticPlugin();
#endif

	PluginNameMap::iterator it = mPluginNameMap.begin();
	for (; it != mPluginNameMap.end(); ++it)
	{
#ifdef FG_DYNAMIC_PLUGIN
		LoadPluginLibrary(it->first);
#else
		LoadStaticPlugin(it->first);
#endif
	}

#ifndef FG_DYNAMIC_PLUGIN
	CheckStaticPlugin();
#endif

	return true;
}

bool FragrantGrass::PluginManager::Awake()
{
	std::cout << "----Awake----" << std::endl;

	PluginInstanceMap::iterator itAfterInstance = mPluginInstanceMap.begin();
	for (; itAfterInstance != mPluginInstanceMap.end(); itAfterInstance++)
	{
		SetCurrentPlugin(itAfterInstance->second);
		itAfterInstance->second->Awake();
	}

	return true;
}

inline bool FragrantGrass::PluginManager::Init()
{
	std::cout << "----Init----" << std::endl;

	PluginInstanceMap::iterator itInstance = mPluginInstanceMap.begin();
	for (; itInstance != mPluginInstanceMap.end(); itInstance++)
	{
		SetCurrentPlugin(itInstance->second);
		itInstance->second->Init();
	}

   mxCoroutineManager.Init(CoroutineExecute);

	return true;
}

bool FragrantGrass::PluginManager::LoadPluginConfig()
{
	std::string strContent;
	std::string strFilePath = GetConfigPath() + mstrConfigName;
	
	GetFileContent(strFilePath, strContent);
	if (strContent.length() == 0)
	{
		printf("LoadPluginConfig Path = %s failed\n", strFilePath.c_str());
		return false;
	}

	rapidxml::xml_document<> xDoc;
	xDoc.parse<0>((char*)strContent.c_str());

    rapidxml::xml_node<>* pRoot = xDoc.first_node();
    rapidxml::xml_node<>* pAppNameNode = pRoot->first_node(mstrAppName.c_str());
    if (!pAppNameNode)
    {
		std::cerr << "[PluginManager::LoadPluginConfi]: AppName = " << mstrAppName << " Does Not Exist !" << std::endl;
        FGASSERT(0, "There are no App ID", __FILE__, __FUNCTION__);
        return false;
    }

    for (rapidxml::xml_node<>* pPluginNode = pAppNameNode->first_node("Plugin"); pPluginNode; pPluginNode = pPluginNode->next_sibling("Plugin"))
    {
        const char* strPluginName = pPluginNode->first_attribute("Name")->value();

        mPluginNameMap.insert(PluginNameMap::value_type(strPluginName, true));

		//std::cout << strPluginName << std::endl;
    }

    return true;
}

bool FragrantGrass::PluginManager::LoadStaticPlugin()
{

#ifndef FG_DYNAMIC_PLUGIN

//for nf-sdk plugins
//	CREATE_PLUGIN(this, NFActorPlugin)
//	CREATE_PLUGIN(this, NFConfigPlugin)
//	CREATE_PLUGIN(this, NFKernelPlugin)
	CREATE_PLUGIN(this, ConfigPlugin)
	CREATE_PLUGIN(this, LogPlugin)
//	CREATE_PLUGIN(this, NFLuaScriptPlugin)
//	CREATE_PLUGIN(this, NFNavigationPlugin)
	CREATE_PLUGIN(this, NetPlugin)
//	CREATE_PLUGIN(this, NFNoSqlPlugin)
//	CREATE_PLUGIN(this, NFScalePlugin)
	CREATE_PLUGIN(this, SecurityPlugin)
//	CREATE_PLUGIN(this, NFTestPlugin)
//
////DB
//	CREATE_PLUGIN(this, NFDBLogicPlugin)
//	CREATE_PLUGIN(this, NFDBNet_ClientPlugin)
//	CREATE_PLUGIN(this, NFDBNet_ServerPlugin)
//
////GAME
//	CREATE_PLUGIN(this, NFGameLogicPlugin)
//	CREATE_PLUGIN(this, NFGameServerNet_ClientPlugin)
//	CREATE_PLUGIN(this, NFGameServerNet_ServerPlugin)
//	CREATE_PLUGIN(this, NFGameServerPlugin)
//
////LOGIN
//	CREATE_PLUGIN(this, NFLoginLogicPlugin)
//	CREATE_PLUGIN(this, NFLoginNet_ClientPlugin)
//	CREATE_PLUGIN(this, NFLoginNet_ServerPlugin)
//	CREATE_PLUGIN(this, NFLoginNet_HttpServerPlugin)
//
//MASTER
//	CREATE_PLUGIN(this, NFMasterNet_HttpServerPlugin)
	CREATE_PLUGIN(this, MasterNetServerPlugin)
//
////PROXY
	CREATE_PLUGIN(this, ProxyLogicPlugin)
	CREATE_PLUGIN(this, ProxyServerNetClientPlugin)
	CREATE_PLUGIN(this, ProxyServerNetServerPlugin)
//
//WORLD
//	CREATE_PLUGIN(this, NFWorldLogicPlugin)
	CREATE_PLUGIN(this, WorldNetClientPlugin)
	CREATE_PLUGIN(this, WorldNetServerPlugin)
//
////MIDWARE
//	CREATE_PLUGIN(this, NFChatPlugin)
//	CREATE_PLUGIN(this, NFFriendPlugin)
//	CREATE_PLUGIN(this, NFClanPlugin)
//	CREATE_PLUGIN(this, NFHeroPlugin)
//	CREATE_PLUGIN(this, NFItemBagPlugin)
//	CREATE_PLUGIN(this, NFMailPlugin)
//	CREATE_PLUGIN(this, NFRankPlugin)
//	CREATE_PLUGIN(this, NFShopPlugin)
//	CREATE_PLUGIN(this, NFSkillPlugin)
//	CREATE_PLUGIN(this, NFTaskPlugin)
//	CREATE_PLUGIN(this, NFUserGiftPlugin)
#endif

    return true;
}

bool FragrantGrass::PluginManager::CheckStaticPlugin()
{
#ifndef FG_DYNAMIC_PLUGIN
	//plugin
	for (auto it = mPluginInstanceMap.begin(); it != mPluginInstanceMap.end();)
	{
		bool bFind = false;
		const std::string& strPluginName = it->first;
		for (int i = 0; i < mStaticPlugin.size(); ++i)
		{
			const std::string& tempPluginName = mStaticPlugin[i];
			if (tempPluginName == strPluginName)
			{
				bFind = true;
			}
		}

		if (!bFind)
		{
			it = mPluginInstanceMap.erase(it);  
		}
		else
		{
			it++;
		}
	}

	for (auto it = mPluginInstanceMap.begin(); it != mPluginInstanceMap.end(); ++it)
	{
		std::cout << it->first << std::endl;
	}

	std::cout << "-------------" << std::endl;

	//////module
	for (auto it = mModuleInstanceMap.begin(); it != mModuleInstanceMap.end();)
	{
		bool bFind = false;
		const std::string& strModuleName = it->first;

		for (int i = 0; i < mStaticPlugin.size(); ++i)
		{
			const std::string& strPluginName = mStaticPlugin[i];
				
			IPlugin* pPlugin = this->FindPlugin(strPluginName);
			if (pPlugin)
			{
				IModule* pModule = pPlugin->GetElement(strModuleName);
				if (pModule)
				{
					bFind = true;
					break;
				}
			}
		}

		if (!bFind)
		{
			it = mModuleInstanceMap.erase(it);  
		}
		else
		{
			it++;
		}
	}

	std::cout << "-------------" << std::endl;

	for (auto it = mModuleInstanceMap.begin(); it != mModuleInstanceMap.end(); ++it)
	{
		std::cout << it->first << std::endl;
	}
#endif

    return true;
}

bool FragrantGrass::PluginManager::LoadStaticPlugin(const std::string& strPluginDLLName)
{
	mStaticPlugin.push_back(strPluginDLLName);

	return true;
}

void FragrantGrass::PluginManager::Registered(IPlugin* plugin)
{
    const std::string& strPluginName = plugin->GetPluginName();
    if (!FindPlugin(strPluginName))
	{
		mPluginInstanceMap.insert(PluginInstanceMap::value_type(strPluginName, plugin));
		IPlugin* temp = mCurrentPlugin;
		SetCurrentPlugin(plugin);
        plugin->Install();
		SetCurrentPlugin(temp);
    }
	else
	{
		std::cout << strPluginName << std::endl;
		assert(0);
	}
}

void FragrantGrass::PluginManager::UnRegistered(IPlugin* plugin)
{
    PluginInstanceMap::iterator it = mPluginInstanceMap.find(plugin->GetPluginName());
    if (it != mPluginInstanceMap.end())
    {
        it->second->Uninstall();
        delete it->second;
        it->second = NULL;
        mPluginInstanceMap.erase(it);
    }
}

bool FragrantGrass::PluginManager::ReLoadPlugin(const std::string & strPluginDLLName)
{
	//1.shut all module of this plugin
	//2.unload this plugin
	//3.load new plugin
	//4.init new module
	//5.tell others who has been reloaded
	PluginInstanceMap::iterator itInstance = mPluginInstanceMap.find(strPluginDLLName);
	if (itInstance == mPluginInstanceMap.end())
	{
		return false;
	}
	//1
	IPlugin* pPlugin = itInstance->second;
	IModule* pModule = pPlugin->First();
	while (pModule)
	{
		pModule->BeforeShut();
		pModule->Shut();
		pModule->Finalize();

		pModule = pPlugin->Next();
	}

	//2
	PluginLibMap::iterator it = mPluginLibMap.find(strPluginDLLName);
	if (it != mPluginLibMap.end())
	{
		DynLib* pLib = it->second;
		DLL_STOP_PLUGIN_FUNC pFunc = (DLL_STOP_PLUGIN_FUNC)pLib->GetSymbol("DllStopPlugin");

		if (pFunc)
		{
			pFunc(this);
		}

		pLib->UnLoad();

		delete pLib;
		pLib = NULL;
		mPluginLibMap.erase(it);
	}

	//3
	DynLib* pLib = new DynLib(strPluginDLLName);
	bool bLoad = pLib->Load();
	if (bLoad)
	{
		mPluginLibMap.insert(PluginLibMap::value_type(strPluginDLLName, pLib));

		DLL_START_PLUGIN_FUNC pFunc = (DLL_START_PLUGIN_FUNC)pLib->GetSymbol("DllStartPlugin");
		if (!pFunc)
		{
			std::cout << "Reload Find function DllStartPlugin Failed in [" << pLib->GetName() << "]" << std::endl;
			assert(0);
			return false;
		}

		pFunc(this);
	}
	else
	{
#if FG_PLATFORM == FG_PLATFORM_LINUX
		char* error = dlerror();
		if (error)
		{
			std::cout << stderr << " Reload shared lib[" << pLib->GetName() << "] failed, ErrorNo. = [" << error << "]" << std::endl;
			std::cout << "Reload [" << pLib->GetName() << "] failed" << std::endl;
			assert(0);
			return false;
		}
#elif FG_PLATFORM == FG_PLATFORM_WIN
		std::cout << stderr << " Reload DLL[" << pLib->GetName() << "] failed, ErrorNo. = [" << GetLastError() << "]" << std::endl;
		std::cout << "Reload [" << pLib->GetName() << "] failed" << std::endl;
		assert(0);
		return false;
#endif // FG_PLATFORM
	}

	//4
	PluginInstanceMap::iterator itReloadInstance = mPluginInstanceMap.begin();
	for (; itReloadInstance != mPluginInstanceMap.end(); itReloadInstance++)
	{
		if (strPluginDLLName != itReloadInstance->first)
		{
			itReloadInstance->second->OnReloadPlugin();
		}
	}
	return true;
}

IPlugin* FragrantGrass::PluginManager::FindPlugin(const std::string& strPluginName)
{
    PluginInstanceMap::iterator it = mPluginInstanceMap.find(strPluginName);
    if (it != mPluginInstanceMap.end())
    {
        return it->second;
    }

    return NULL;
}

bool FragrantGrass::PluginManager::Execute()
{
    mnNowTime = time(NULL);

    bool bRet = true;

    PluginInstanceMap::iterator it = mPluginInstanceMap.begin();
    for (; it != mPluginInstanceMap.end(); ++it)
    {
        bool tembRet = it->second->Execute();
        bRet = bRet && tembRet;
    }

    return bRet;
}

inline int FragrantGrass::PluginManager::GetAppID() const
{
	return mnAppID;
}

inline void FragrantGrass::PluginManager::SetAppID(const int nAppID)
{
    mnAppID = nAppID;
}

bool FragrantGrass::PluginManager::IsRunningDocker() const
{
	return mbIsDocker;
}

void FragrantGrass::PluginManager::SetRunningDocker(bool bDocker)
{
	mbIsDocker = bDocker;
}

bool FragrantGrass::PluginManager::IsStaticPlugin() const
{
	return mbStaticPlugin;
}

inline INT64 FragrantGrass::PluginManager::GetInitTime() const
{
	return mnInitTime;
}

inline INT64 FragrantGrass::PluginManager::GetNowTime() const
{
	return mnNowTime;
}

inline const std::string & FragrantGrass::PluginManager::GetConfigPath() const
{
	return mstrConfigPath;
}

inline void FragrantGrass::PluginManager::SetConfigPath(const std::string & strPath)
{
	mstrConfigPath = strPath;
}

void FragrantGrass::PluginManager::SetConfigName(const std::string & strFileName)
{
	if (strFileName.empty())
	{
		return;
	}

	if (strFileName.find(".xml") == string::npos)
	{
		return;
	}

#ifdef FG_DEBUG_MODE
	mstrConfigName = "DataCfg/Debug/" + strFileName;
#else
	mstrConfigName = "DataCfg/Release/" + strFileName;
#endif
}

const std::string& FragrantGrass::PluginManager::GetConfigName() const
{
	return mstrConfigName;
}

const std::string& FragrantGrass::PluginManager::GetAppName() const
{
	return mstrAppName;
}

void FragrantGrass::PluginManager::SetAppName(const std::string& strAppName)
{
	if (!mstrAppName.empty())
	{
		return;
	}

	mstrAppName = strAppName;
}

const std::string & FragrantGrass::PluginManager::GetLogConfigName() const
{
	return mstrLogConfigName;
}

void FragrantGrass::PluginManager::SetLogConfigName(const std::string & strName)
{
	mstrLogConfigName = strName;
}

IPlugin * FragrantGrass::PluginManager::GetCurrentPlugin()
{
	return mCurrentPlugin;
}

IModule * FragrantGrass::PluginManager::GetCurrenModule()
{
	return mCurrenModule;
}

void FragrantGrass::PluginManager::SetCurrentPlugin(IPlugin * pPlugin)
{
	mCurrentPlugin = pPlugin;
}

void FragrantGrass::PluginManager::SetCurrenModule(IModule * pModule)
{
	mCurrenModule = pModule;
}

void FragrantGrass::PluginManager::SetGetFileContentFunctor(GET_FILECONTENT_FUNCTOR fun)
{
	mGetFileContentFunctor = fun;
}

bool FragrantGrass::PluginManager::GetFileContent(const std::string &strFileName, std::string &strContent)
{
	if (mGetFileContentFunctor)
	{
		return mGetFileContentFunctor(strFileName, strContent);
	}

	FILE *fp = fopen(strFileName.c_str(), "rb");
	if (!fp)
	{
		return false;
	}

	if (-1 == fseek(fp, 0, SEEK_END))
	{
		perror("PluginManager::GetFileContent fseek failed");
		fclose(fp);
		return false;
	}
	const long filelength = ftell(fp);
	if (-1 == fseek(fp, 0, SEEK_SET))
	{
		perror("PluginManager::GetFileContent fseek failed");
		fclose(fp);
		return false;
	}
	strContent.resize(filelength);
	size_t elementCnt = 1;
	size_t readCnt = fread((void*)strContent.data(), filelength, elementCnt, fp);
	if (readCnt != elementCnt)
	{
		perror("PluginManager::GetFileContent fread failed");
		fclose(fp);
		return false;
	}
	fclose(fp);

	return true;
}

void FragrantGrass::PluginManager::AddModule(const std::string& strModuleName, IModule* pModule)
{
	ModuleInstanceMap::iterator it = mModuleInstanceMap.find(strModuleName);
    if (it == mModuleInstanceMap.end())
    {
		bool succeed = mModuleInstanceMap.insert(ModuleInstanceMap::value_type(strModuleName, pModule)).second;
		if (succeed)
		{
			if(mCurrentPlugin && !mCurrentPlugin->strName.empty())
				printf("[AddModule] ==> [%s] add [%s] succeed\n", mCurrentPlugin->strName.c_str(), strModuleName.c_str());
			else
				printf("[AddModule] ==> [%s] succeed\n", strModuleName.c_str());
		}
		else
		{
			if (mCurrentPlugin && !mCurrentPlugin->strName.empty())
				printf("[AddModule] ==> [%s] add [%s] failed\n", mCurrentPlugin->strName.c_str(), strModuleName.c_str());
			else
				printf("[AddModule] ==> [%s] failed\n", strModuleName.c_str());
		}
    }
	else
	{
		if (mCurrentPlugin && !mCurrentPlugin->strName.empty())
			printf("[AddModule] ==> [%s] add [%s] failed module has already existed\n", mCurrentPlugin->strName.c_str(), strModuleName.c_str());
		else
			printf("[AddModule] ==> [%s] failed module has already existed\n", strModuleName.c_str());
	}
}

void FragrantGrass::PluginManager::AddTestModule(const std::string& strModuleName, IModule* pModule)
{
	if (!FindTestModule(strModuleName))
	{
		mTestModuleInstanceMap.insert(TestModuleInstanceMap::value_type(strModuleName, pModule));
	}
}

void FragrantGrass::PluginManager::RemoveModule(const std::string& strModuleName)
{
    ModuleInstanceMap::iterator it = mModuleInstanceMap.find(strModuleName);
    if (it != mModuleInstanceMap.end())
    {
        mModuleInstanceMap.erase(it);
    }
}

IModule* FragrantGrass::PluginManager::FindModule(const std::string& strModuleName)
{
	ModuleInstanceMap::iterator it = mModuleInstanceMap.find(strModuleName);
	if (it != mModuleInstanceMap.end())
	{
		if(mCurrenModule && !mCurrenModule->strName.empty())
			printf("[FindModule] ===> [%s] find [%s] succeed\n", mCurrenModule->strName.c_str(),strModuleName.c_str());
		else
			printf("[FindModule] ===> [%s] succeed\n", strModuleName.c_str());
		return it->second;
	}
	
	if (mCurrenModule && !mCurrenModule->strName.empty())
		printf("[FindModule] ===> [%s] find [%s] failed\n", mCurrenModule->strName.c_str(), strModuleName.c_str());
	else
		printf("[FindModule] ===> [%s] failed\n", strModuleName.c_str());

    return NULL;
}

IModule* FragrantGrass::PluginManager::FindTestModule(const std::string& strModuleName)
{
	std::string strSubModuleName = strModuleName;

#if FG_PLATFORM == FG_PLATFORM_WIN
	std::size_t position = strSubModuleName.find(" ");
	if (string::npos != position)
	{
		strSubModuleName = strSubModuleName.substr(position + 1, strSubModuleName.length());
	}
#else
	for (int i = 0; i < strSubModuleName.length(); i++)
	{
		std::string s = strSubModuleName.substr(0, i + 1);
		int n = atof(s.c_str());
		if (strSubModuleName.length() == i + 1 + n)
		{
			strSubModuleName = strSubModuleName.substr(i + 1, strSubModuleName.length());
			break;
		}
	}
#endif

    TestModuleInstanceMap::iterator it = mTestModuleInstanceMap.find(strSubModuleName);
	if (it != mTestModuleInstanceMap.end())
	{
		return it->second;
	}

	return NULL;
}

std::list<IModule*> FragrantGrass::PluginManager::Modules()
{
	std::list<IModule*> xModules;

	ModuleInstanceMap::iterator itCheckInstance = mModuleInstanceMap.begin();
	for (; itCheckInstance != mModuleInstanceMap.end(); itCheckInstance++)
	{
		xModules.push_back(itCheckInstance->second);
	}

	return xModules;
}

bool FragrantGrass::PluginManager::AfterInit()
{
	std::cout << "----AfterInit----" << std::endl;

    PluginInstanceMap::iterator itAfterInstance = mPluginInstanceMap.begin();
    for (; itAfterInstance != mPluginInstanceMap.end(); itAfterInstance++)
    {
		SetCurrentPlugin(itAfterInstance->second);
        itAfterInstance->second->AfterInit();
    }

    return true;
}

bool FragrantGrass::PluginManager::CheckConfig()
{
	std::cout << "----CheckConfig----" << std::endl;

    PluginInstanceMap::iterator itCheckInstance = mPluginInstanceMap.begin();
    for (; itCheckInstance != mPluginInstanceMap.end(); itCheckInstance++)
    {
		SetCurrentPlugin(itCheckInstance->second);
        itCheckInstance->second->CheckConfig();
    }

    return true;
}

bool FragrantGrass::PluginManager::ReadyExecute()
{
	std::cout << "----ReadyExecute----" << std::endl;

    PluginInstanceMap::iterator itCheckInstance = mPluginInstanceMap.begin();
    for (; itCheckInstance != mPluginInstanceMap.end(); itCheckInstance++)
    {
		SetCurrentPlugin(itCheckInstance->second);
        itCheckInstance->second->ReadyExecute();
    }

    return true;
}

bool FragrantGrass::PluginManager::BeforeShut()
{
    PluginInstanceMap::iterator itBeforeInstance = mPluginInstanceMap.begin();
    for (; itBeforeInstance != mPluginInstanceMap.end(); itBeforeInstance++)
    {
		SetCurrentPlugin(itBeforeInstance->second);
        itBeforeInstance->second->BeforeShut();
    }

    return true;
}

bool FragrantGrass::PluginManager::Shut()
{
    PluginInstanceMap::iterator itInstance = mPluginInstanceMap.begin();
    for (; itInstance != mPluginInstanceMap.end(); ++itInstance)
    {
		SetCurrentPlugin(itInstance->second);
        itInstance->second->Shut();
    }

    return true;
}

bool FragrantGrass::PluginManager::Finalize()
{
	PluginInstanceMap::iterator itInstance = mPluginInstanceMap.begin();
	for (; itInstance != mPluginInstanceMap.end(); itInstance++)
	{
		SetCurrentPlugin(itInstance->second);
		itInstance->second->Finalize();
	}

	////////////////////////////////////////////////

	PluginNameMap::iterator it = mPluginNameMap.begin();
	for (; it != mPluginNameMap.end(); it++)
	{
#ifdef FG_DYNAMIC_PLUGIN
		UnLoadPluginLibrary(it->first);
#else
		UnLoadStaticPlugin(it->first);
#endif
	}

	mPluginInstanceMap.clear();
	mPluginNameMap.clear();

	return true;
}

bool FragrantGrass::PluginManager::LoadPluginLibrary(const std::string& strPluginDLLName)
{
    PluginLibMap::iterator it = mPluginLibMap.find(strPluginDLLName);
    if (it == mPluginLibMap.end())
    {
        DynLib* pLib = new DynLib(strPluginDLLName);
        bool bLoad = pLib->Load();

        if (bLoad)
        {
            mPluginLibMap.insert(PluginLibMap::value_type(strPluginDLLName, pLib));

            DLL_START_PLUGIN_FUNC pFunc = (DLL_START_PLUGIN_FUNC)pLib->GetSymbol("DllStartPlugin");
            if (!pFunc)
            {
                std::cout << "Find function DllStartPlugin Failed in [" << pLib->GetName() << "]" << std::endl;
                assert(0);
                return false;
            }

            pFunc(this);

            return true;
        }
        else
        {
#if FG_PLATFORM == FG_PLATFORM_LINUX || FG_PLATFORM == FG_PLATFORM_APPLE
            char* error = dlerror();
            if (error)
            {
                std::cout << stderr << " Load shared lib[" << pLib->GetName() << "] failed, ErrorNo. = [" << error << "]" << std::endl;
                std::cout << "Load [" << pLib->GetName() << "] failed" << std::endl;
                assert(0);
                return false;
            }
#elif FG_PLATFORM == FG_PLATFORM_WIN
            std::cout << stderr << " Load DLL[" << pLib->GetName() << "] failed, ErrorNo. = [" << GetLastError() << "]" << std::endl;
            std::cout << "Load [" << pLib->GetName() << "] failed" << std::endl;
            assert(0);
            return false;
#endif // FG_PLATFORM
        }
    }

    return false;
}

bool FragrantGrass::PluginManager::UnLoadPluginLibrary(const std::string& strPluginDLLName)
{
    PluginLibMap::iterator it = mPluginLibMap.find(strPluginDLLName);
    if (it != mPluginLibMap.end())
    {
        DynLib* pLib = it->second;
        DLL_STOP_PLUGIN_FUNC pFunc = (DLL_STOP_PLUGIN_FUNC)pLib->GetSymbol("DllStopPlugin");

        if (pFunc)
        {
            pFunc(this);
        }

        pLib->UnLoad();

        delete pLib;
        pLib = NULL;
        mPluginLibMap.erase(it);

        return true;
    }

    return false;
}

bool FragrantGrass::PluginManager::UnLoadStaticPlugin(const std::string & strPluginDLLName)
{
	//     DESTROY_PLUGIN(this, NFConfigPlugin)
	//     DESTROY_PLUGIN(this, NFEventProcessPlugin)
	//     DESTROY_PLUGIN(this, NFKernelPlugin)
	return false;
}

void FragrantGrass::PluginManager::ExecuteCoScheduler()
{
    mxCoroutineManager.ScheduleJob();
}

void FragrantGrass::PluginManager::YieldCo(const int64_t nSecond)
{
	mxCoroutineManager.YieldCo(nSecond);
}

void FragrantGrass::PluginManager::YieldCo()
{
   mxCoroutineManager.YieldCo();
}
